﻿
using System;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;

[AddComponentMenu("BToolkit/CButton")]
public class CButton : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IPointerClickHandler, IPointerEnterHandler, IPointerExitHandler
{
    public enum Transition { None, Scale, Color, Sprite, Texture }
    [Serializable]
    public class ButtonUnityEvent : UnityEvent<int, string> { }

    public static Action buttonCommonSoundAction;

    public Text text;
    public float triggerInterval = 1;
    public bool globalSound = true;
    public RectTransform rectTransform { get { return transform as RectTransform; } }
    private Action onPress, onRelease, onClick, onDoubleClick, onMouseEnter, onMouseOut;
    private float canPressTime, canReleaseTime, canClickTime, canDoubleClickTime, doubleClickTime;
    private int currPointerId = -1;

    //点击变换效果
    public Transition transition = Transition.Scale;
    public MaskableGraphic transTarget;
    public float pressScale = 0.98f;
    public Color pressColor = new Color(0.95f, 0.95f, 0.95f, 1);
    public Sprite pressSprite;
    public Texture2D pressTexture;
    public bool useNativeSize;

    private Color colorDefault;
    private Sprite defaultSprite;
    private Texture defaultTexture;
    private Vector3 defaultScale;
    private Vector2 touchPos;
    private Canvas canvas;
    private Camera uiCamera;

    void Awake()
    {
        //点击变换效果
        if (!transTarget)
        {
            transTarget = GetComponent<MaskableGraphic>();
        }
        if (transTarget)
        {
            if (transTarget is Image)
            {
                defaultSprite = (transTarget as Image).sprite;
            }
            else if (transTarget is RawImage)
            {
                defaultTexture = (transTarget as RawImage).texture;
            }
            colorDefault = transTarget.color;
        }
    }

    void OnEnable()
    {
        canPressTime = 0;
        canReleaseTime = 0;
        canClickTime = 0;
        canDoubleClickTime = 0;
    }

    void Start()
    {
        CanvasScaler canvasScaler = rectTransform.GetComponentInParent<CanvasScaler>();
        canvas = canvasScaler.GetComponent<Canvas>();
        if (canvas && canvas.renderMode != RenderMode.ScreenSpaceOverlay)
        {
            uiCamera = canvas.worldCamera;
        }
    }

    public void OnPointerDown(PointerEventData eventData)
    {
        if (enabled)
        {
            touchPos = ScreenToUGUIPoint(eventData.position);
            if (canPressTime < Time.time)
            {
                canPressTime = Time.time + triggerInterval;
                if (onPress != null)
                {
                    onPress.Invoke();
                }

                if (globalSound) buttonCommonSoundAction?.Invoke();

                //点击变换效果
                if (transTarget)
                {
                    switch (transition)
                    {
                        case Transition.Scale:
                            if (defaultScale == Vector3.zero)
                            {
                                defaultScale = transTarget.transform.localScale;
                            }
                            transTarget.transform.localScale = defaultScale * pressScale;
                            break;
                        case Transition.Color:
                            transTarget.color = pressColor;
                            break;
                        case Transition.Sprite:
                            if (pressSprite)
                            {
                                (transTarget as Image).sprite = pressSprite;
                                if (useNativeSize) transTarget.SetNativeSize();
                            }
                            break;
                        case Transition.Texture:
                            if (pressTexture)
                            {
                                (transTarget as RawImage).texture = pressTexture;
                                if (useNativeSize) transTarget.SetNativeSize();
                            }
                            break;
                    }
                }
            }
            currPointerId = eventData.pointerId;
        }
    }

    public void OnPointerUp(PointerEventData eventData)
    {
        bool canExecUp = true;
        if (Application.isMobilePlatform)
        {
            canExecUp = (currPointerId == eventData.pointerId);
        }
        if (canExecUp)
        {
            if (canReleaseTime < Time.time)
            {
                canReleaseTime = Time.time + triggerInterval;
                if (onRelease != null)
                {
                    onRelease.Invoke();
                }
            }
            currPointerId = -1;

            //变换效果恢复
            TransResume();
        }
    }

    private void TransResume()
    {
        if (transTarget)
        {
            switch (transition)
            {
                case Transition.Scale:
                    if (defaultScale != Vector3.zero) transTarget.transform.localScale = defaultScale;
                    break;
                case Transition.Color:
                    if (colorDefault != new Color(0, 0, 0, 0)) transTarget.color = colorDefault;
                    break;
                case Transition.Sprite:
                    if (defaultSprite)
                    {
                        (transTarget as Image).sprite = defaultSprite;
                        if (useNativeSize) transTarget.SetNativeSize();
                    }
                    break;
                case Transition.Texture:
                    if (defaultTexture)
                    {
                        (transTarget as RawImage).texture = defaultTexture;
                        if (useNativeSize) transTarget.SetNativeSize();
                    }
                    break;
            }
        }
    }

    private Vector2 ScreenToUGUIPoint(Vector2 screenPos)
    {
        RectTransformUtility.ScreenPointToLocalPointInRectangle(canvas.transform as RectTransform, screenPos, uiCamera, out Vector2 uiPos);
        return uiPos;
    }

    public void OnPointerClick(PointerEventData eventData)
    {
        if (enabled)
        {
            if (canClickTime < Time.time)
            {
                canClickTime = Time.time + triggerInterval;
                if (onClick != null)
                {
                    Vector2 pos = ScreenToUGUIPoint(eventData.position);
                    if (Vector2.Distance(pos, touchPos) < 50)
                    {
                        onClick.Invoke();
                    }
                }
            }

            if (doubleClickTime > Time.time)
            {
                doubleClickTime = 0;
                if (canDoubleClickTime < Time.time)
                {
                    canDoubleClickTime = Time.time + triggerInterval;
                    onDoubleClick?.Invoke();
                }
            }
            else
            {
                doubleClickTime = Time.time + 0.5f;
            }

        }
    }

    public void OnPointerEnter(PointerEventData eventData)
    {
        onMouseEnter?.Invoke();
    }

    public void OnPointerExit(PointerEventData eventData)
    {
        onMouseOut?.Invoke();
    }

    public void SetPress(Action action)
    {
        onPress = action;
    }
    public void RemovePress()
    {
        onPress = null;
        TransResume();
    }

    public void SetRelease(Action action)
    {
        onRelease = action;
    }
    public void RemoveUp()
    {
        onRelease = null;
        TransResume();
    }

    public void SetClick(Action action)
    {
        onClick = action;
    }
    public void RemoveClick()
    {
        onClick = null;
        TransResume();
    }

    public void SetDoubleClick(Action action)
    {
        onDoubleClick = action;
    }

    public void SetMouseEnter(Action action)
    {
        onMouseEnter = action;
    }

    public void SetMouseOut(Action action)
    {
        onMouseOut = action;
    }

    public void RemoveDoubleClick()
    {
        onDoubleClick = null;
        TransResume();
    }

    public void ClearAllEvents()
    {
        onClick = null;
        onPress = null;
        onRelease = null;
        onDoubleClick = null;
        TransResume();
    }

    /// <summary>
    /// 外部改变缩放值后重设这里的缩放值
    /// </summary>
    public void SetDefaultScale(Vector3 sacle)
    {
        defaultScale = sacle;
    }

#if UNITY_EDITOR
    [UnityEditor.MenuItem("BToolkit/创建 CButton")]
    [UnityEditor.MenuItem("GameObject/BToolkit/创建 CButton")]
    static void Create()
    {
        GameObject go = new GameObject("Btn");
        go.layer = LayerMask.NameToLayer("UI");
        go.transform.SetParent(UnityEditor.Selection.activeGameObject.transform, false);
        go.AddComponent<Image>();
        go.AddComponent<CButton>();
        UnityEditor.EditorUtility.SetDirty(go);
    }
#endif
}